﻿
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Linq;
using agsXMPP;
using agsXMPP.protocol.client;
using sharpxbot.Core.Security;
using sharpxbot.Plugins.Base;
using sharpxbot.Plugins.Context;
using sharpxbot.Utils.Logging;
namespace sharpxbot.Core.Plugins
{
    public class GroupChatRulesPlugin : AbstractPlugin
    {
        private static readonly Guid PluginGuid = new Guid("22aae290-7925-4e29-a8dc-052730bd9c30");

        public const string PluginDataPathSuffix = "GroupChatRules/";

        public string RulesBanner { get; set; }

        public override PluginPermissions NeededPermissions
        {
            get { return PluginPermissions.Everyone; }
        }

        public override string Name
        {
            get { return "GroupChatRulesPlugin"; }
        }

        public override string Author
        {
            get { return "tillias"; }
        }

        public override Guid GUID
        {
            get { return PluginGuid; }
        }

        public override string Description
        {
            get { return "Displays group-chat rules for every new user of chat (e.g. non-member)"; }
        }

        public override string Usage
        {
            get { return "This is automatic plugin. No commands allowed"; }
        }

        public GroupChatRulesPlugin(IPluginContext context) :
            base(context)
        {
            RulesBanner = LoadRulesBanner(context.PluginDataPath);

            presenceDictionary = new HashSet<Jid>();
        }

        public override void ProcessMessage(Message message)
        {
        }

        public override void ProcessPresence(Presence presence)
        {
            if (RulesBanner == string.Empty)
                return;

            if (IsGroupChatPresence(presence))
            {
                Jid publicJid = presence.From;

                if (presence.Type == PresenceType.unavailable)
                {
                    presenceDictionary.Remove(publicJid);
                }
                else
                {
                    if (!AlreadySentBanner(publicJid))
                    {
                        presenceDictionary.Add(publicJid);

                        try
                        {
                            agsXMPP.protocol.x.muc.Item item = presence.MucUser.Item;
                            if (item != null)
                            {
                                if (ShouldSendBanner(item))
                                {
                                    Message message = new Message()
                                    {
                                        Type = MessageType.chat,
                                        To = presence.From,
                                        Body = RulesBanner
                                    };

                                    Context.Channel.Send(message);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Logger.Write("GroupChatRulesPlugin unxepected error", ex, LogMessageType.Fatal);
                        }
                    }
                }
            }
        }

        private bool AlreadySentBanner(Jid publicJid)
        {
            return presenceDictionary.Contains(publicJid);
        }

        private static bool ShouldSendBanner(agsXMPP.protocol.x.muc.Item item)
        {
            return item.Affiliation == agsXMPP.protocol.x.muc.Affiliation.none ||
                                        item.Affiliation == agsXMPP.protocol.x.muc.Affiliation.outcast;
        }

        #region Private methods

        private string LoadRulesBanner(string path)
        {
            string result = String.Empty;

            string bannerFileName = path + "/" + PluginDataPathSuffix + "/" + "banner.xml";

            FileInfo f = new FileInfo(bannerFileName);
            if (f.Exists)
            {
                try
                {
                    XDocument doc = XDocument.Load(bannerFileName);
                    XElement bannerElement = doc.Element("banner");
                    if (bannerElement != null)
                    {
                        result = bannerElement.Value;
                    }
                }
                catch (Exception ex)
                {
                    Logger.Write("Can't load rules banner. Group-chat rules plugin won't work", ex, LogMessageType.Error);
                }
            }

            return result;
        }

        #endregion

        #region Private fields

        HashSet<Jid> presenceDictionary;

        #endregion
    }
}
